use rustcloud_core::{CircuitBreakerState, CircuitBreakerMetrics};
use std::time::{Duration, Instant, SystemTime};

/// 熔断器状态机实现
#[derive(Debug, Clone)]
pub struct StateMachine {
    state: CircuitBreakerState,
    failure_count: u32,
    success_count: u32,
    total_calls: u64,
    failed_calls: u64,
    last_failure_time: Option<SystemTime>,
    next_retry_time: Option<Instant>,
    half_open_calls: u32,
}

impl StateMachine {
    pub fn new() -> Self {
        Self {
            state: CircuitBreakerState::Closed,
            failure_count: 0,
            success_count: 0,
            total_calls: 0,
            failed_calls: 0,
            last_failure_time: None,
            next_retry_time: None,
            half_open_calls: 0,
        }
    }

    pub fn record_success(&mut self, half_open_success_threshold: u32) {
        self.total_calls += 1;
        self.failure_count = 0;
        
        if self.state == CircuitBreakerState::HalfOpen {
            self.success_count += 1;
            if self.success_count >= half_open_success_threshold {
                self.reset();
            }
        }
    }

    pub fn record_failure(&mut self, failure_threshold: u32, recovery_timeout: Duration) {
        self.total_calls += 1;
        self.failed_calls += 1;
        self.failure_count += 1;
        self.last_failure_time = Some(SystemTime::now());
        
        if self.state == CircuitBreakerState::HalfOpen {
            self.trip(recovery_timeout);
        } else if self.failure_count >= failure_threshold {
            self.trip(recovery_timeout);
        }
    }

    pub fn can_attempt(&self) -> bool {
        match self.state {
            CircuitBreakerState::Closed => true,
            CircuitBreakerState::HalfOpen => true,
            CircuitBreakerState::Open => {
                if let Some(next_retry) = self.next_retry_time {
                    Instant::now() >= next_retry
                } else {
                    false
                }
            }
        }
    }

    pub fn transition_to_half_open_if_ready(&mut self) {
        if self.state == CircuitBreakerState::Open && self.can_attempt() {
            self.state = CircuitBreakerState::HalfOpen;
            self.half_open_calls = 0;
            self.success_count = 0;
        }
    }

    fn trip(&mut self, recovery_timeout: Duration) {
        self.state = CircuitBreakerState::Open;
        self.next_retry_time = Some(Instant::now() + recovery_timeout);
    }

    pub fn reset(&mut self) {
        self.state = CircuitBreakerState::Closed;
        self.failure_count = 0;
        self.success_count = 0;
        self.half_open_calls = 0;
        self.next_retry_time = None;
    }

    pub fn metrics(&self) -> CircuitBreakerMetrics {
        CircuitBreakerMetrics {
            total_calls: self.total_calls,
            failed_calls: self.failed_calls,
            success_calls: self.total_calls.saturating_sub(self.failed_calls),
            last_failure_time: self.last_failure_time,
            state: self.state,
        }
    }

    pub fn state(&self) -> CircuitBreakerState {
        self.state
    }
    
    /// 获取失败次数
    pub fn failure_count(&self) -> u32 {
        self.failure_count
    }
    
    /// 获取半开状态调用次数
    pub fn half_open_calls(&self) -> u32 {
        self.half_open_calls
    }
    
    /// 增加半开状态调用次数
    pub fn increment_half_open_calls(&mut self) {
        self.half_open_calls += 1;
    }
    
    /// 强制打开熔断器
    pub fn force_open(&mut self, recovery_timeout: Duration) {
        self.trip(recovery_timeout);
    }
}
